#include "BondDetailTitle.h"

#include <bondlib/BondCalendar.h>
#include <bondlib/BondContainer.h>
#include <bondlib/BondLiquidity.h>
#include <bondlib/QBBondCrmClause.h>
#include <core/ImageMgr.h>
#include <core/StyleMgr.h>
#include <include/CmdDefines.h>
#include <uam/ServerTimeMgr.h>

#include <QHBoxLayout>
#include <QLabel>
#include <QMenu>
#include <QMouseEvent>
#include <QPushButton>
#include <QVBoxLayout>
#include <array>

#include "../BondUtility.h"
#include "../QbBondModule.h"
#include "BondDetailData.h"
#include "BondDetailForm.h"
#include "BondDetailTitleEdit.h"
#include "ui_BondDetailForm.h"

BondDetailTitle::BondDetailTitle(QWidget* p) : QWidget(p) {
  m_edit = new BondDetailTitleEdit(this);
  m_edit->setFixedSize(500, 40);
  QVBoxLayout* mainLayout = new QVBoxLayout(this);
  mainLayout->setContentsMargins(1, 0, 0, 4);
  setLayout(mainLayout);

  QHBoxLayout* nameLayout = new QHBoxLayout();
  nameLayout->setSpacing(1);
  nameLayout->setContentsMargins(0, 0, 0, 0);
  mainLayout->addLayout(nameLayout);
  // mainLayout->addStretch();
  {
    QColor color = StyleMgr::instance().color("StaticTextBK");
    m_details = new BondDetailForm(this);
    m_details->setStyleSheet(
        QString("QLabel { background-color: #%1; padding-left: 4px; "
                "padding-right: 4px; border-radius: 2px;} QFrame { "
                "background-color: #%1; border-radius: 2px;}")
            .arg(color.rgb(), 0, 16));
    mainLayout->addWidget(m_details);
    mainLayout->setSpacing(2);

    m_details->ui->Holiday->setFixedSize({26, 16});
    m_details->ui->Holiday->setStyleSheet(
        QString("QLabel#Text   { background-color: #35393b; color: #f9c152; "
                "border-top-right-radius: 0px; border-bottom-right-radius: 0px;"
                "  border: 1px solid;"
                "  border-color: #f9c152;"
                "  padding-left: 1px; padding-right: 2px;"
                "}"
                "QLabel#Number { background-color: #f9c152; color: #35393b; "
                "border-top-left-radius: 0px; border-bottom-left-radius: 0px;"
                "  padding-left: 1px; padding-right: 1px;"
                "}"));
    m_details->ui->Holiday->installEventFilter(this);
    m_details->ui->Holiday->setMouseTracking(true);
  }

  nameLayout->addWidget(m_edit);

  {
    m_markers_container = new QHBoxLayout();
    m_markers_container->setSpacing(4);
    m_markers_container->setContentsMargins(0, 14, 0, 12);
    nameLayout->addLayout(m_markers_container);
  }

  {
    m_title = new QLabel("", this);
    m_title->setStyleSheet("QLabel { text-decoration: underline; }");
    m_title->setCursor(QCursor(Qt::PointingHandCursor));
    nameLayout->addWidget(m_title);
    /*
     * m_title->setText("<a style='color: red; text-decoration: none' href =
    https://blog.csdn.net/wmcy123?type=lately>点我试试");

     * connect(m_title, &QLabel::linkActivated, [=](QString url){
        QDesktopServices::openUrl(QUrl(url));
    });*/
  }
  nameLayout->addStretch();
  {
    std::array<QPushButton**, 4> buttons = {&m_toolBar_calc, &m_toolBar_quote,
                                            &m_toolBar_prev, &m_toolBar_next};
    for (int i = 0; i < (int)buttons.size(); ++i) {
      QPushButton** btn = buttons[i];
      *btn = new QPushButton(this);
      (*btn)->setFixedSize(24, 24);
      nameLayout->addWidget(*btn);

      if (i < 2) {
        (*btn)->installEventFilter(this);
        (*btn)->setMouseTracking(true);
      }
    }
  }
  nameLayout->setSpacing(2);

  setMouseTracking(true);
}

void BondDetailTitle::setDetailData(QSharedPointer<DetailData> d) {
  m_data = d;

  m_edit->setDetailData(d);

  fillIssuer();
  fillDetails();
  connect(d.get(), SIGNAL(hisPriceChanged()), this, SLOT(update()));
  connect(d.get(), SIGNAL(issueInfoChanged()), this, SLOT(update()));
  connect(d.get(), SIGNAL(cdcChanged()), this, SLOT(update()));

  update();
}

void BondDetailTitle::insertMarker(const QString& marker,
                                   const QColor& bkColor) {
  QLabel* lbl = new QLabel(marker, this);
  lbl->setStyleSheet(QString("QLabel { background-color: #%1; padding-left: "
                             "6px; padding-right: 6px; border-radius: 2px;}")
                         .arg(bkColor.rgb(), 0, 16));
  m_markers_container->addWidget(lbl);
}

bool BondDetailTitle::eventFilter(QObject* watched, QEvent* event) {
  if (event->type() == QEvent::HoverEnter) {
    if (watched == m_toolBar_calc) {
      QMenu* menu = new QMenu(this);
      menu->setAttribute(Qt::WA_DeleteOnClose);
      menu->addAction(
          tr("债券价格试算"));  //, this, [=]() {onMenuClicked(BROKERDAILY); }
      menu->addAction(tr("持有期计算器"));
      menu->popup(mapToGlobal(m_toolBar_calc->frameGeometry().bottomLeft()));
    } else if (watched == m_toolBar_quote) {
      QMenu* menu = new QMenu(this);
      menu->setAttribute(Qt::WA_DeleteOnClose);
      menu->addAction(tr("行情小窗"));
      menu->addAction(tr("利差小窗"));
      menu->popup(mapToGlobal(m_toolBar_quote->frameGeometry().bottomLeft()));
    }
  }

  if (watched == m_details->ui->Holiday) {
    if (!m_tipCalendar) {
      m_tipCalendar.reset(new SCalendar());
      m_tipCalendar->setFixedSize(264, 306);
    }

    if (event->type() == QEvent::Enter) {
      if (!m_tipCalendar->isVisible()) {
        const QPoint& pos =
            mapToGlobal(m_details->ui->Holiday->frameGeometry().bottomRight());
        m_tipCalendar->setGeometry(pos.x() + 15, pos.y() + 15,
                                   m_tipCalendar->width(),
                                   m_tipCalendar->height());
        m_tipCalendar->setSelectedDate(m_maturityDay);
        m_tipCalendar->setStart(m_maturityDay);
        m_tipCalendar->setEnd(m_maturityDay);
      }
      m_tipCalendar->show();
    } else if (event->type() == QEvent::Leave) {
      m_tipCalendar->hide();
    }
  }

  return false;
}

void BondDetailTitle::paintEvent(QPaintEvent* event) {
  QStylePainter painter(this);
  painter.setPen(Qt::NoPen);
  QColor bkColor = StyleMgr::instance().color("BasicPlate");
  painter.setBrush(bkColor);
  painter.drawRect(rect());

  computeDrawRect();
  if (m_data) {
    // fillIssuer();
    fillDetails();
  }

  // fillDetails();
}

void BondDetailTitle::mousePressEvent(QMouseEvent* event) {
  if (event->button() == Qt::LeftButton) {
    //判断鼠标位置，若在发行人位置上则切换到F10发行人界面
    QPoint mousePos = event->pos();

    if (m_rcIssuer.contains(mousePos)) {
      QString param = "issuerCode=";
      param.append(m_data->bond().GetIssuerCode());

      QbBondModule::instance().app()->execCommand(CMD_IssuerInformation,
                                                  param.toUtf8());
    } else if (m_rcCRM.contains(mousePos)) {
      jumpCrmBond();
    }
  }
}

void BondDetailTitle::mouseMoveEvent(QMouseEvent* event) {
  QPoint mousePos = event->pos();
  if (m_rcIssuer.contains(mousePos)) {
    this->setCursor(Qt::PointingHandCursor);
  } else {
    this->setCursor(Qt::ArrowCursor);
  }

#if 0
    bool isShowCalendar = false;
	if (m_rcHoliday.contains(mousePos))
	{
		if (!m_tipCalendar)
		{
            m_tipCalendar.reset( new SCalendar() );
			m_tipCalendar->setFixedSize(264, 306);
		}
	
		if (!m_tipCalendar->isVisible())
		{
			int x = mapToGlobal(mousePos).x();
			int y = mapToGlobal(mousePos).y();
			m_tipCalendar->setGeometry( x + 15, y + 15, m_tipCalendar->width(), m_tipCalendar->height());
			m_tipCalendar->setSelectedDate(m_maturityDay);
			m_tipCalendar->setStart(m_maturityDay);
			m_tipCalendar->setEnd(m_maturityDay);
		}
		m_tipCalendar->show();
		isShowCalendar = true;
	}

	if (!isShowCalendar && m_tipCalendar)
	{
		m_tipCalendar->hide();
	}
#endif
}

void BondDetailTitle::paintLabel(QStylePainter& painter, QRect& issueRect,
                                 const QString& label) {
  const int LabelHeight = 16;
  QRect labelRect = issueRect;
  int yOffset = (issueRect.height() - LabelHeight) / 2;
  labelRect.adjust(0, yOffset, 0, -yOffset);

  QFontMetrics fm(painter.font(), this);
  int w = fm.horizontalAdvance(label);
  labelRect.setWidth(w + 12 * 2);

  painter.setPen(Qt::NoPen);
  painter.drawRoundedRect(labelRect, 2, 2);
  painter.setPen(StyleMgr::instance().color("TextNormal"));
  painter.drawText(labelRect, label, QTextOption(Qt::AlignCenter));

  issueRect.setLeft(labelRect.right() + 8);
}

void BondDetailTitle::paintCRM(QStylePainter& painter, QRect& issueRect,
                               const QString& label, QColor bkColor) {
  const int height = 20;

  QRect labelRect = issueRect;
  int yOffset = (issueRect.height() - height) / 2;
  labelRect.adjust(0, yOffset, 0, -yOffset);

  QFontMetrics fm(painter.font(), this);
  int w = fm.horizontalAdvance(label);
  labelRect.setWidth(w + 12 * 2);

  m_rcCRM = labelRect;

  const int nEllipse = 5;
  painter.setPen(Qt::NoPen);
  painter.setBrush(bkColor);

  painter.drawEllipse(
      QRect(labelRect.left(), labelRect.top(), nEllipse * 2, height));
  painter.drawEllipse(QRect(labelRect.right() - nEllipse * 2, labelRect.top(),
                            nEllipse * 2, height));

  int x = labelRect.left() + nEllipse;
  painter.drawRect(
      QRect(x, labelRect.top(), labelRect.width() - 2 * nEllipse, height));

  painter.setPen(StyleMgr::instance().color("TextNormal"));
  painter.drawText(labelRect, label, QTextOption(Qt::AlignCenter));

  issueRect.setLeft(labelRect.right() + 8);
}

QString removeTrailingZeros(const QString& str) {
  if (!str.contains('.')) {
    return str;
  }

  QString result = str;
  int index = result.size() - 1;
  while (index >= 0 && result.at(index) == '0') {
    result.remove(index, 1);
    index--;
  }
  // 移除尾部的点（如果有的话）
  if (result.size() > 0 && result.at(result.size() - 1) == '.') {
    result.chop(1);
  }
  return result;
}

QPair<QString, QColor> getBP(const QString& price, const QString& preclose) {
  QString m_strBP;
  QColor m_clrBP = StyleMgr::instance().color("HighLightWord");
  ;
  // BP
  bool bvalidPrc = false;
  bool bvalidYesPr = false;
  const double dbPrc = price.toDouble(&bvalidPrc);
  const double dbYesPrc = preclose.toDouble(&bvalidYesPr);
  if ((bvalidPrc && dbPrc > -0.0001) && (dbYesPrc && dbYesPrc > -0.0001)) {
    if ((dbPrc > 29.9999 && dbYesPrc > 29.9999) ||
        (dbPrc < 30 && dbYesPrc < 30)) {
      double dbBp = dbPrc - dbYesPrc;
      QString strTemp, strAdd;
      if (dbPrc < 30) {
        strAdd = "BP";  //(NewStringTable.GetLanguageID() == SSS_LANGID_ENG_NEW)
                        //? _T("bps"): _T("BP");
      }
      if (dbBp > 0.0001 || dbBp < -0.0001) {
        if (dbPrc < 30) dbBp *= 100;
        strTemp.sprintf("%.2f", dbBp);
        strTemp = strTemp.trimmed();
        // m_strBP.Format(_T("%s%s"),
        // SSA2W(CSSTools::PriceRemoveZero(SSW2A(strTemp).c_str(), 0).c_str()),
        // strAdd);
        m_strBP = QString("%1%2").arg(removeTrailingZeros(strTemp), strAdd);
        if (dbBp > 0.0001) {
          m_strBP.insert(0, '+');
          m_clrBP = StyleMgr::instance().color(
              "Down_Reduce_H1");  // NAMED_COLOR(crDown_Reduce_H1);
        } else {
          m_clrBP = StyleMgr::instance().color(
              "Up_Increase_H1");  // NAMED_COLOR(crUp_Increase_H1);
        }
      } else {
        m_strBP = "0BP";
      }
    }
  }

  return {m_strBP, m_clrBP};
}

static const QString NDATA = "--";

QString GetBondLiquidity(const CBondInfo& info) {
  const int bondIndex =
      CBondContainer::instance().GetBondIndex(info.GetCombBondKey());
  xQBBondLiquidityUnit unit;
  if (CBondLiquidity::instance().GetLiquidity(bondIndex, unit)) {
    int liqScore = std::round(atof(unit.m_liquid));
    return QString("%1 / %2").arg(unit.m_liquidLevel).arg(liqScore);
  }

  return NDATA;
}

inline const QString& NoDataOnEmpty(const QString& s) {
  return s.isEmpty() ? NDATA : s;
}

#if 1
void BondDetailTitle::fillDetails() {
  QColor bsDir;
  if (m_data->titleParams().m_strTrade == "TKN")
    bsDir = StyleMgr::instance().color("Ofr_TKN_H1");
  else if (m_data->titleParams().m_strTrade == "GVN")
    bsDir = StyleMgr::instance().color("Bid_GVN_H1");
  else if (m_data->titleParams().m_strTrade == "TRD")
    bsDir = StyleMgr::instance().color("Down_Reduce_H1");
  else
    bsDir = StyleMgr::instance().color("Highlight");

  const QColor Highlight = StyleMgr::instance().color("Highlight");
  const QColor DealTKN = StyleMgr::instance().color("Deal_TKN");
  const QColor DealGVN = StyleMgr::instance().color("Deal_GVN");

  // const QString template_Interest = "<html><head/><body><p>票面利率 <span
  // style=\" font-weight:bold; color:#%2;\">%1</span> 年度</p></body></html>";
  const QString template_html = "<html><head/><body><p>%1</p></body></html>";
  const QString template_bold_color =
      "<span style=\" font-weight:bold; color:#%2;\">%1</span>";
  const QString template_bold = "<span style=\" font-weight:bold;\">%1</span>";

  auto IsCDCImpIssuerAndRating = [](const CBondInfo& bi) -> bool {
    return (bi.IsBondCountry() || bi.IsBondCenter() || bi.IsBondGKZ() ||
            (strcmp(bi.GetBondSubType(), "PBB") == 0 &&
             strcmp(bi.GetIssuerCode(), "Z000189") == 0) ||
            (strcmp(bi.GetBondSubType(), "PBB") == 0 &&
             strcmp(bi.GetIssuerCode(), "Z000207") == 0));
  };

  const bool bCDCImpIssuerAndRating = IsCDCImpIssuerAndRating(m_data->bond());
  const bool bInterestBond = m_data->bond().is_interest_bond();
  const bool bCreditBond = m_data->bond().is_credit_bond();

  m_details->ui->RemainingDuration->setText(
      ((template_html.arg("剩余期限 %1"))
           .arg(template_bold.arg(m_data->titleParams().m_strRemain))));
  m_details->ui->ExpireDate->setText(
      (template_html.arg("到期日 %1"))
          .arg(template_bold.arg("XXXX-XX-XX")));  // TODO: 到期日|兑付日|行权日
  m_details->ui->Interest->setText(
      ((template_html.arg("票面利率 %1 年度")).arg(template_bold_color))
          .arg(m_data->titleParams().m_strInterest)
          .arg(Highlight.rgb(), 0, 16));
  m_details->ui->RatePattern->setText(
      (template_html.arg("利率方式 %1"))
          .arg(template_bold.arg(m_data->titleParams().m_strRatePattern)));

  //主体评级/债项评级/中债隐含评级展示更新,对于国债、央票和政金债（国开、口行、农发）隐藏不显示;利率债的中证隐含评级不显示
  m_details->ui->Issuer->setVisible(!bCDCImpIssuerAndRating);
  m_details->ui->Rating->setVisible(!bCDCImpIssuerAndRating);
  m_details->ui->CDCImplied->setVisible((!bCDCImpIssuerAndRating) &&
                                        (!bInterestBond));
  m_details->ui->CSIDefaultRate->setVisible(!bInterestBond);

  if (m_details->ui->Issuer->isVisible()) {
    m_details->ui->Issuer->setText(
        (template_html.arg("主体评级 %2 %1"))
            .arg(template_bold.arg(
                m_data->titleParams().m_strIssuerInstituteName))
            .arg(template_bold_color.arg(m_data->titleParams().m_strIssuer)
                     .arg(Highlight.rgb(), 0, 16)));
  }

  if (m_details->ui->Rating->isVisible()) {
    m_details->ui->Rating->setText(
        (template_html.arg("债项评级 %2 %1"))
            .arg(template_bold.arg(
                m_data->titleParams().m_strRatingInstituteName))
            .arg(template_bold_color.arg(m_data->titleParams().m_strRating)
                     .arg(Highlight.rgb(), 0, 16)));
  }

  if (m_details->ui->CDCImplied->isVisible()) {
    m_details->ui->CDCImplied->setText(
        (template_html.arg("中债隐含 %1"))
            .arg(template_bold_color.arg(m_data->titleParams().m_strCDCImplied)
                     .arg(Highlight.rgb(), 0, 16)));
  }

  m_details->ui->ChinaDCRate->setText(
      (template_html.arg("中债 %1 %2 %3"))
          .arg(template_bold.arg(m_data->titleParams().m_strApp))
          .arg(template_bold_color.arg(m_data->titleParams().m_strAppClean)
                   .arg(Highlight.rgb(), 0, 16))
          .arg(template_bold.arg(m_data->titleParams().m_strAppDate)));
  m_details->ui->CSI->setText(
      (template_html.arg("中证 %1 %2 %3"))
          .arg(template_bold.arg(m_data->titleParams().m_strZZ))
          .arg(template_bold_color.arg(m_data->titleParams().m_strZZClean)
                   .arg(Highlight.rgb(), 0, 16))
          .arg(template_bold.arg(m_data->titleParams().m_strZZDate)));
  m_details->ui->CBMD->setText((template_html.arg("中债修正久期 %1 %2"))
                                   .arg(template_bold.arg("X"))
                                   .arg(template_bold.arg("Y")));

  const auto& BP = getBP(m_data->titleParams().m_strRealPrice,
                         m_data->titleParams().m_strYestodayPrc);
  m_details->ui->NEW->setText(
      (template_html.arg("最新成交 %1"))
          .arg(template_bold_color.arg(m_data->titleParams().m_strRealPrice)
                   .arg(BP.second.rgb(), 0, 16)));
  m_details->ui->BP->setText(
      (template_html.arg("%1 %2"))
          .arg(template_bold_color
                   .arg(NoDataOnEmpty(m_data->titleParams().m_strTrade))
                   .arg(bsDir.rgb(), 0, 16))
          .arg(template_bold_color.arg(NoDataOnEmpty(BP.first))
                   .arg(BP.second.rgb(), 0, 16)));
  m_details->ui->CLOSE->setText(
      (template_html.arg("昨收 %1"))
          .arg(template_bold.arg(m_data->titleParams().m_strYestodayPrc)));
  m_details->ui->OPEN->setText(
      (template_html.arg("今开 %1"))
          .arg(template_bold.arg(
              m_data->titleParams()
                  .m_strOpenPrc)));  //(QString("<p>今开
                                     //<b>%1</b></p>").arg(m_data->titleParams().m_strOpenPrc));
  m_details->ui->HIGH->setText(
      (template_html.arg("最高 %1"))
          .arg(template_bold.arg(m_data->titleParams().m_strHighPrc)));
  m_details->ui->LOW->setText(
      (template_html.arg("最低 %1"))
          .arg(template_bold.arg(m_data->titleParams().m_strLowPrc)));
  m_details->ui->VolumeOfBusiness->setText(
      (template_html.arg("笔数 %1"))
          .arg(template_bold_color.arg(m_data->titleParams().m_strTransCount)
                   .arg(Highlight.rgb(), 0, 16)));
  m_details->ui->TKN->setText(
      (template_html.arg("%1 %2"))
          .arg(template_bold_color.arg("TKN").arg(DealTKN.rgb(), 0, 16))
          .arg(template_bold_color.arg(m_data->titleParams().m_strTKNCount)
                   .arg(Highlight.rgb(), 0, 16)));
  m_details->ui->GVN->setText(
      (template_html.arg("%1 %2"))
          .arg(template_bold_color.arg("GVN").arg(DealGVN.rgb(), 0, 16))
          .arg(template_bold_color.arg(m_data->titleParams().m_strGVNCount)
                   .arg(Highlight.rgb(), 0, 16)));
  QString OutStandingAmount = "--";
  const double fAmount = m_data->bond().GetOutstandingAmount();
  if (fAmount < 0.0001) {
    // OutStandingAmount = _T("--");
  } else {
    OutStandingAmount.sprintf("%.02f亿", fAmount / 10000);  // 亿 or Bn
  }
  m_details->ui->Balance->setText(
      (template_html.arg("债券余额 %1"))
          .arg(template_bold.arg(OutStandingAmount)));

  const QString& scorlevel = GetBondLiquidity(m_data->bond());
  m_details->ui->Liquidity->setText(
      (template_html.arg("流动性 %1"))
          .arg(template_bold.arg(
              scorlevel))  // m_data->titleParams().m_strScorLevel
  );

  if (m_details->ui->CSIDefaultRate->isVisible()) {
    m_details->ui->CSIDefaultRate->setText(
        (template_html.arg("中证隐含违约率 %1"))
            .arg(
                "XX")  // template_bold.arg(m_data->titleParams().m_strCSIDefaultRating
    );
  }
  if (m_strHolidayDays.isEmpty()) {
    m_details->ui->Holiday->hide();
  } else {
    m_details->ui->Holiday->show();
    m_details->ui->Holiday->setDayCount(m_strHolidayDays);
  }
}
#else
void BondDetailTitle::fillDetails() {
  QStylePainter painter(this);
  int needDrawCount = m_data->firstBond() ? rectRealPrcName : rectMaxCount;

  QColor bsDir;
  if (m_data->titleParams().m_strTrade == "TKN")
    bsDir = StyleMgr::instance().color("Ofr_TKN_H1");
  else if (m_data->titleParams().m_strTrade == "GVN")
    bsDir = StyleMgr::instance().color("Bid_GVN_H1");
  else if (m_data->titleParams().m_strTrade == "TRD")
    bsDir = StyleMgr::instance().color("Down_Reduce_H1");
  else
    bsDir = StyleMgr::instance().color("Highlight");
  ;

  //绘制标签底色
  for (int i = 0; i < needDrawCount;) {
    QRect r = m_rects[i];
    if (i == rectRealPrcName) {
      r.setRight(m_rects[i + 3].right());
      i += 4;
    } else {
      r.setRight(m_rects[i + 1].right());
      i += 2;
    }

    painter.setPen(Qt::NoPen);
    painter.setBrush(StyleMgr::instance().color("PartPlate"));
    painter.drawRoundedRect(r, 2, 2);
  }

  QTextOption txtOption(Qt::AlignLeft | Qt::AlignVCenter);
  //绘制内容
  QString strDraw;
  QFontMetrics fmName(font());
  QFont f = font();
  f.setBold(true);
  QFontMetrics fmValue(f);
  for (int i = 0; i < needDrawCount; ++i) {
    strDraw = GetValue(i);
    if (i == rectCDCValue || i == rectCSValue) {
      QRect rcCDC = m_rects[i];
      if (strDraw == tr("无权限", "DetailAuth")) {
        SImage* img = ImgMgr::instance().image("widgets_icon_authority_lock");
        int left = m_rects[i].left();
        int top = m_rects[i].center().y() - img->height() / 2 + 1;
        painter.drawImage(QPoint(left, top), *img);

        rcCDC.setLeft(rcCDC.left() + img->width() + 2);
        // TODO remember rect to tip
        DrawShowText(rcCDC, strDraw, &painter,
                     StyleMgr::instance().color("SupportingWord"), font(),
                     txtOption, true);
      } else if (!strDraw.isEmpty()) {
        QStringList stAry = strDraw.split('|');
        int begin = 0;
        for (int nCD = 0; nCD < stAry.length(); ++nCD) {
          if (stAry[nCD].isEmpty()) continue;

          QRect rcDrawCDC = rcCDC;
          rcDrawCDC.moveLeft(rcDrawCDC.left() + begin);
          int cdWidth = fmValue.horizontalAdvance(stAry[nCD]);
          if (nCD == 0) {
            DrawShowText(rcDrawCDC, stAry[nCD], &painter,
                         StyleMgr::instance().color("Highlight"), font(),
                         txtOption, true);
          } else if (nCD == 1) {
            DrawShowText(rcDrawCDC, stAry[nCD], &painter,
                         StyleMgr::instance().color("TextNormal"), font(),
                         txtOption, true);
            if (i == rectCDCValue && m_data->titleParams().m_bShowFullPrice &&
                !stAry[nCD].isEmpty() && stAry[nCD] != "--") {
              SImage* img =
                  ImgMgr::instance().image("widgets_grid_tag_fullprice");
              int nCDCLeft = rcDrawCDC.left() + cdWidth + 2;
              int nCDCTop = m_rects[nCD].center().y() - img->height() / 2 + 1;
              painter.drawImage(QPoint(nCDCLeft, nCDCTop), *img);
              begin += img->width() + 4;
            }
          } else
            DrawShowText(rcDrawCDC, stAry[nCD], &painter,
                         StyleMgr::instance().color("SupportingWord"), font(),
                         txtOption, true);

          begin += cdWidth + 4;
        }
      }
    } else if (i == (int)rectRemainName || i == (int)rectRateName ||
               i == (int)rectBodyName || i == (int)rectIssRatingName ||
               i == (int)rectCdcImpliedName || i == (int)rectRealPrcName ||
               i == (int)rectYestodayName || i == (int)rectOpenPrcName ||
               i == (int)rectMaxPrcName || i == (int)rectMinPrcName ||
               i == (int)rectPrcNumbName || i == (int)rectCDCName ||
               i == (int)rectCSName || i == (int)rectRatePatternName ||
               i == (int)rectScoreLevelName) {
      DrawShowText(m_rects[i], strDraw, &painter,
                   StyleMgr::instance().color("TextNormal"), font(),
                   QTextOption(Qt::AlignRight | Qt::AlignVCenter), false);
    } else if (i == (int)rectRealPrcDirec) {
      DrawShowText(m_rects[i], strDraw, &painter, bsDir, font(), txtOption,
                   true);
    } else if (i == (int)rectRealBP) {
      DrawShowText(m_rects[i], strDraw, &painter, m_data->titleParams().m_clrBP,
                   font(), txtOption, true);
    } else if (i == (int)rectRealPrc) {
      DrawShowText(m_rects[i], strDraw, &painter, m_data->titleParams().m_clrBP,
                   font(), txtOption, true);
    } else if (i == rectBodyValue || i == rectIssRatingValue) {
      QStringList stAry = strDraw.split('|');
      if (stAry.length() == 1)
        DrawShowText(m_rects[i], strDraw, &painter,
                     StyleMgr::instance().color("Highlight"), font(), txtOption,
                     true);
      else if (stAry.length() > 0) {
        int w = fmValue.horizontalAdvance(stAry[0]);
        QRect rcRt, rcComp;
        rcRt = rcComp = m_rects[i];
        rcRt.setWidth(w + 1);
        rcComp.setLeft(rcRt.right() + 4);

        DrawShowText(rcRt, stAry[0], &painter,
                     StyleMgr::instance().color("Highlight"), font(), txtOption,
                     true);
        DrawShowText(rcComp, stAry[1], &painter,
                     StyleMgr::instance().color("SupportingWord"), font(),
                     txtOption, true);
      }
    } else if (i == rectRemainValue) {
      DrawShowText(m_rects[i], strDraw, &painter,
                   StyleMgr::instance().color("Highlight"), font(), txtOption,
                   true);
      if (m_nHolidayType != emHolidayNull) {
        int left = m_rcHoliday.left();
        SImage* img = ImgMgr::instance().image(m_nHolidayType == emHolidayCib
                                                   ? "widgets_cell_xiu_cib"
                                                   : "widgets_cell_xiu_sse");
        painter.drawImage(left, m_rcHoliday.top(), *img);
        left += img->width();

        img = ImgMgr::instance().image(m_nHolidayType == emHolidayCib
                                           ? "widgets_cell_xiu_cib_number"
                                           : "widgets_cell_xiu_sse_number");
        QRect r(left, m_rcHoliday.top(), m_rcHoliday.right() - left,
                m_rcHoliday.height());
        painter.drawImage(r, *img);
        painter.save();
        painter.setPen(Qt::black);
        QFont f = font();
        f.setPixelSize(10);
        painter.setFont(f);
        painter.drawText(
            QRect(left, m_rcHoliday.top(), m_rcHoliday.right() - left,
                  m_rcHoliday.height()),
            m_strHolidayDays, QTextOption(Qt::AlignCenter));
        painter.restore();
      }
    } else if (i == rectCdcImpliedValue)  //中债隐含评级
    {
      QRect rcCDC = m_rects[i];
      if (strDraw == tr("无权限", "DetailAuth")) {
        SImage* img = ImgMgr::instance().image("widgets_icon_authority_lock");
        int left = m_rects[i].left();
        int top = m_rects[i].center().y() - img->height() / 2 + 1;
        painter.drawImage(QRect(left, top, img->width(), img->height()), *img);

        rcCDC.setLeft(rcCDC.left() + img->width() + 2);
        DrawShowText(rcCDC, strDraw, &painter,
                     StyleMgr::instance().color("SupportingWord"), font(),
                     txtOption, true);
      } else
        DrawShowText(m_rects[i], strDraw, &painter,
                     StyleMgr::instance().color("Highlight"), font(), txtOption,
                     true);
    } else
      DrawShowText(m_rects[i], strDraw, &painter,
                   StyleMgr::instance().color("Highlight"), font(), txtOption,
                   true);
  }
}
#endif
void BondDetailTitle::fillIssuer() {
  const CBondInfo& bond = m_data->bond();
  if (!bond.IsValidBond()) return;

  QColor color = StyleMgr::instance().color("ButtonNormal");

  //绘制标签
  QString strAsset = "";
  if (bond.CheckAssetStatus(CBondContainer::AssetPri))  //私募
  {
    strAsset = tr("私募", "AssetStatus");
  } else if (bond.CheckAssetStatus(CBondContainer::AssetNull))  //公募
  {
    strAsset = tr("公募", "AssetStatus");
  } else if (bond.CheckAssetStatus(CBondContainer::AssetPub))  //小公募
  {
    strAsset = tr("小公募", "AssetStatus");
  } else if (strcmp(bond.GetBondSubType(), "LLB") == 0) {
    if (strcmp(bond.GetEntCor(), "SMB") == 0)
      strAsset = tr("一般债", "AssetStatus");
    else if (strcmp(bond.GetEntCor(), "NMB") == 0)
      strAsset = tr("专项债", "AssetStatus");
  }

  if (!strAsset.isEmpty()) {
    insertMarker(strAsset, color);
  }

  time_t t1, t2;
  BondUtility::calcOptDate(bond, t1, t2);
  time_t now = ServerTimeMgr::instance().serverTime();
  bool buyBack = t1 > now;
  bool sellBack = t2 > now;

  QString optionLabel1, optionLabel2;
  QString optType = QString::fromLocal8Bit(bond.GetOptionTypeName(false));
  if (sellBack && optType.compare(QStringLiteral("回售权")) == 0)
    optionLabel1 = tr("回售", "OptionType");
  else if (buyBack && optType.compare(QStringLiteral("赎回权")) == 0)
    optionLabel1 = tr("赎回", "OptionType");
  else if (optType.compare(QStringLiteral("永续债")) == 0)
    optionLabel1 = tr("永续", "OptionType");
  else if (optType.compare(QStringLiteral("回售权和赎回权")) == 0) {
    if (sellBack) optionLabel1 = tr("回售", "OptionType");
    if (buyBack) optionLabel2 = tr("赎回", "OptionType");
  }

  if (!optionLabel1.isEmpty()) insertMarker(optionLabel1, color);

  if (!optionLabel2.isEmpty()) insertMarker(optionLabel2, color);

  //新增次级标签
  if ((strcmp(bond.GetBondSubType(), "PSB") == 0) ||
      (strcmp(bond.GetBondSubType(), "TET") == 0) ||
      (strcmp(bond.GetBondSubType(), "SES") == 0) ||
      (strcmp(bond.GetBondSubType(), "CSB") ==
       0))  // PSB为金融债里的次级债，TET为二级资本工具类型的次级债，SES证券公司次级债，CSB商业银行次级债
  {
    QString subordinateLabel = tr("次级债", "OptionType");
    insertMarker(subordinateLabel, color);
  }

  {
    QFont f = font();
    f.setPixelSize(16);
    m_title->setFont(f);
    m_title->setText(m_data->titleParams().m_companyName.isEmpty()
                         ? "未取到公司名称"
                         : m_data->titleParams().m_companyName);
  }
#if 0
	//发行人 TODO:考虑空间展示不全的情况
	painter.save();
	QFont f2 = font();
	f2.setPixelSize(16);
	f2.setUnderline(true);
	painter.setFont(f2);
	painter.setPen(StyleMgr::instance().color("Highlight"));
	painter.drawText(rectIssue, m_data->titleParams().m_companyName, QTextOption(Qt::AlignLeft | Qt::AlignVCenter));
	QFontMetrics fm(f2);
	int w = fm.horizontalAdvance(m_data->titleParams().m_companyName);

	m_rcIssuer = rectIssue;
	m_rcIssuer.setRight(rectIssue.left() + w);

	painter.restore();

	rectIssue.setLeft(rectIssue.left() + w + 4);

	//CRM
	if (m_data->showCrmLink())
	{
		if (m_data->crmType() == crm_crm || m_data->crmType() == crm_cln) {
			paintCRM(painter, rectIssue, m_data->crmString(), QColor(15, 108, 94));
			/* TODO：
			if (m_nMouseState == crm_normal) crBack.SetFromCOLORREF(RGB(15, 108, 94));
			else if (m_nMouseState == crm_hover) crBack.SetFromCOLORREF(RGB(13, 94, 82));
			else crBack.SetFromCOLORREF(RGB(9, 62, 54));
			*/
		}
		else {
			paintCRM(painter, rectIssue, m_data->crmString(), QColor(9, 75, 187));
			/*
			if (m_nMouseState == crm_normal) crBack.SetFromCOLORREF(RGB(9, 75, 187));
			else if (m_nMouseState == crm_hover) crBack.SetFromCOLORREF(RGB(9, 68, 168));
			else crBack.SetFromCOLORREF(RGB(7, 61, 148));
			*/
		}
	}
#endif
}

static QString GetFormatIssuerString(const QString& strComp,
                                     const QString& strRating) {
  bool bCompEpt = strComp.isEmpty() || strComp == "--",
       bRatEpt = strRating.isEmpty() || strRating == "--";
  if (bCompEpt || bRatEpt)
    return "--";
  else
    return strRating + "|" + strComp;
}

QString BondDetailTitle::GetValue(int nCurrent) {
  QString strValue = "";
  switch (nCurrent) {
    case (int)rectRemainName:
      return tr("剩余期限", "TitleSecond");
    case (int)rectRateName: {
      if (m_data->titleParams().m_strRatePattern == "贴现" ||
          m_data->titleParams().m_strRatePattern == "Discount")
        return tr("发行收益");
      else
        return tr("票面利率", "TitleSecond");
    } break;
    case (int)rectBodyName:
      return tr("债项评级", "TitleSecond");
    case (int)rectIssRatingName:
      return tr("主体评级", "TitleSecond");
    case (int)rectCdcImpliedName:
      return tr("中债隐含", "TitleSecond");
    case (int)rectRealPrcName:
      return tr("实时行情", "TitleSecond");
    case (int)rectYestodayName:
      return tr("昨收", "TitleSecond");
    case (int)rectOpenPrcName:
      return tr("今开", "TitleSecond");
    case (int)rectMaxPrcName:
      return tr("最高", "TitleSecond");
    case (int)rectMinPrcName:
      return tr("最低", "TitleSecond");
    case (int)rectPrcNumbName:
      return tr("笔数", "TitleSecond");
    case (int)rectCDCName:
      return tr("中债", "TitleSecond");
    case (int)rectCSName:
      return tr("中证", "TitleSecond");
    case (int)rectRatePatternName:
      return tr("利率方式", "TitleSecond");
    case (int)rectScoreLevelName:
      return tr("流动性评分", "TitleSecond");
    case (int)rectRemainValue: {
      return m_data->titleParams().m_strRemain;
    }
    case (int)rectRateValue: {
      return m_data->titleParams().m_strInterest;
    }
    case (int)rectBodyValue: {
      return GetFormatIssuerString(
          m_data->titleParams().m_strRatingInstituteName,
          m_data->titleParams().m_strRating);
    }
    case (int)rectIssRatingValue: {
      return GetFormatIssuerString(
          m_data->titleParams().m_strIssuerInstituteName,
          m_data->titleParams().m_strIssuer);
    }
    /*added by shiy20210719*/
    case (int)rectCdcImpliedValue: {
      if (m_data->titleParams().m_strCDCImplied.isEmpty() ||
          m_data->titleParams().m_strZZ == tr("无权限", "DetailAuth")) {
        return m_data->titleParams().m_strCDCImplied;
      } else {
        return m_data->titleParams().m_strCDCImplied;
      }
    }
    /*end*/
    case (int)rectCDCValue: {
      if (m_data->titleParams().m_strApp.isEmpty() ||
          m_data->titleParams().m_strApp == tr("无权限", "DetailAuth")) {
        return m_data->titleParams().m_strApp;
      } else {
        strValue.append(m_data->titleParams().m_strApp)
            .append("|")
            .append(m_data->titleParams().m_strAppClean)
            .append("|")
            .append(m_data->titleParams().m_strAppDate);
        return strValue;
      }
    }
    case (int)rectCSValue: {
      if (m_data->titleParams().m_strZZ.isEmpty() ||
          m_data->titleParams().m_strZZ == tr("无权限", "DetailAuth")) {
        return m_data->titleParams().m_strZZ;
      } else {
        if ((m_data->titleParams().m_strZZ.isEmpty() ||
             m_data->titleParams().m_strZZ == "--") &&
            (m_data->titleParams().m_strZZClean.isEmpty() ||
             m_data->titleParams().m_strZZClean == "--")) {
          strValue = "--";
        } else {
          strValue
              .append(m_data->titleParams().m_strZZ.isEmpty()
                          ? "--"
                          : m_data->titleParams().m_strZZ)
              .append("|")
              .append(m_data->titleParams().m_strZZClean)
              .append("|")
              .append(m_data->titleParams().m_strZZDate);
        }
        return strValue;
      }
    }
    case (int)rectRealPrc: {
      return m_data->titleParams().m_strRealPrice;
    }
    case (int)rectRealPrcDirec: {
      return m_data->titleParams().m_strTrade;
    }
    case (int)rectRealBP: {
      return m_data->titleParams().m_strBP;
    }
    case (int)rectYestodayPrc: {
      return m_data->titleParams().m_strYestodayPrc;
    }
    case (int)rectOpenPrc: {
      return m_data->titleParams().m_strOpenPrc;
    }
    case (int)rectMaxPrc: {
      return m_data->titleParams().m_strHighPrc;
    }
    case (int)rectMinPrc: {
      return m_data->titleParams().m_strLowPrc;
    }
    case (int)rectPrcNumb: {
      return m_data->titleParams().m_strTransCount;
    }
    case (int)rectRatePatternValue: {
      return m_data->titleParams().m_strRatePattern;
    }
    case (int)rectScoreLevel: {
      if (m_data->titleParams().m_strScorLevel.isEmpty()) {
        strValue = "--";
        return strValue;
      } else {
        return m_data->titleParams().m_strScorLevel;
      }
    }
    default: {
      break;
    }
  }
  return strValue;
}

void BondDetailTitle::computeDrawRect() {
  const int ValueWidth = 44;
  const int height = 24;
  QRect r = rect();
  r.adjust(4, 40, -4, 0);

  QRect rectDraw = r;
  rectDraw.setHeight(height);
  rectDraw.setRight(rectDraw.left() + ValueWidth);

  QFontMetrics fm(font());
  QFont f = font();
  f.setBold(true);
  QFontMetrics fmValue(f);
  QString strDraw;
  for (int i = 0; i < rectRealPrcName; ++i) {
    strDraw = GetValue(i);
    int width = 0;
    if (i == rectCSValue || i == rectCDCValue) {
      if (!strDraw.isEmpty() && strDraw != tr("无权限", "DetailAuth")) {
        QStringList stAry = strDraw.split('|');
        for (int i = 0; i < stAry.length(); ++i) {
          width += fmValue.horizontalAdvance(stAry[i]) + 4;
        }
      } else if (strDraw == tr("无权限", "DetailAuth")) {
        width = fmValue.horizontalAdvance(strDraw);
        width += 12 + 2;
      }

      if (i == rectCDCValue && m_data->titleParams().m_bShowFullPrice) {
        SImage* image = ImgMgr::instance().image("widgets_grid_tag_fullprice");
        if (image) width += image->width() + 4;
      }
    } else if (i == rectBodyValue || i == rectIssRatingValue) {
      QStringList stAry = strDraw.split('|');
      if (stAry.length() == 1)
        width = fmValue.horizontalAdvance(strDraw);
      else if (stAry.length() > 1) {
        width = fmValue.horizontalAdvance(stAry[0]);
        width += fmValue.horizontalAdvance(stAry[1]) + 4;
      }
    } else if (i == rectRemainValue) {
      width = fmValue.horizontalAdvance(strDraw);
      m_rcHoliday.setRect(0, 0, 0, 0);
      // TODO 提前计算
      m_nHolidayType = emHolidayNull;
      m_strHolidayDays.clear();
      if (m_data->bond().IsValidBond()) {
        bool isCIB = true;
        int nDayCIB = 0, nDaySSE = 0;
        if (CBondCalendar::instance().IsHoliday_CHY(m_data->bond(), isCIB,
                                                    nDayCIB, nDaySSE)) {
          if (isCIB) {
            if (nDayCIB == nDaySSE)
              m_strHolidayDays = QString::number(nDayCIB);
            else
              m_strHolidayDays = QString("%1/%2").arg(nDayCIB).arg(nDaySSE);
            m_nHolidayType = emHolidayCib;
          } else {
            m_nHolidayType = emHolidaySSE;
            m_strHolidayDays = QString::number(nDaySSE);
          }
          QString maturityDay =
              QString::number(atoi(m_data->bond().GetMaturityDate()));
          m_maturityDay = QDate::fromString(maturityDay, "yyyyMMdd");
        }

        if (m_nHolidayType != emHolidayNull) {
          int nXiuWidth = 0;
          int nXiuValWidth = 0;
          if (m_nHolidayType == emHolidayCib) {
            nXiuWidth =
                ImgMgr::instance().image("widgets_cell_xiu_cib")->width();
            nXiuValWidth = ImgMgr::instance()
                               .image("widgets_cell_xiu_cib_number")
                               ->width();
          } else {
            nXiuWidth =
                ImgMgr::instance().image("widgets_cell_xiu_sse")->width();
            nXiuValWidth = ImgMgr::instance()
                               .image("widgets_cell_xiu_sse_number")
                               ->width();
          }

          int holidayWidth = nXiuWidth;
          holidayWidth += qMax(fmValue.horizontalAdvance(m_strHolidayDays) + 1,
                               nXiuValWidth);
          int top =
              rectDraw.center().y() -
              ImgMgr::instance().image("widgets_cell_xiu_cib")->height() / 2 +
              1;
          m_rcHoliday.setRect(
              rectDraw.left() + width + 2, top, holidayWidth,
              ImgMgr::instance().image("widgets_cell_xiu_cib")->height());

          width += holidayWidth;
        }
      }
    } else if (i == rectCdcImpliedValue) {
      width = fmValue.horizontalAdvance(strDraw);
      if (strDraw == tr("无权限", "DetailAuth"))
        width +=
            ImgMgr::instance().image("widgets_icon_authority_lock")->width() +
            2;
    } else
      width = fmValue.horizontalAdvance(strDraw);

    //名称和值两侧padding为8
    width += 8;
    if (width > ValueWidth || i % 2 == 0) rectDraw.setWidth(width);

    m_rects[i] = rectDraw;
    if (i != (int)rectRateName && i != (int)rectRateValue) {
      m_rects[i + (int)rectRealPrcName] = rectDraw;
      m_rects[i + (int)rectRealPrcName].moveTop(rectDraw.top() + height + 4);
    }

    rectDraw.moveLeft(rectDraw.right() + 4);
    rectDraw.setWidth(ValueWidth);
  }

  //报价
  strDraw = GetValue(rectRealBP);
  int width = fmValue.horizontalAdvance(strDraw);
  m_rects[rectRealBP] = m_rects[rectRealPrc];
  m_rects[rectRealBP].setRight(m_rects[rectRateValue].right());
  m_rects[rectRealBP].setLeft(m_rects[rectRealBP].right() - 8 - width);

  m_rects[rectRealPrcDirec] = m_rects[rectRealPrc];
  m_rects[rectRealPrcDirec].setLeft(m_rects[rectRealBP].left() - 50);
  m_rects[rectRealPrcDirec].setWidth(40);

  int standWidth = m_rects[rectRatePatternValue].right() -
                   m_rects[rectRatePatternName].left() + 1;
  QRect rt = m_rects[rectRatePatternName];
  rt.setWidth(standWidth);
  rt.moveTop(rt.top() + height + 4);

  for (int i = rectYestodayName; i < rectMaxCount; i += 2) {
    QRect tmpR = rt;
    QString nameStr = GetValue(i);
    width = fm.horizontalAdvance(nameStr);

    tmpR.setWidth(8 + width);
    m_rects[i] = tmpR;

    tmpR.setLeft(tmpR.right() + 4);
    if (i + 1 == rectScoreLevel) {
      nameStr = GetValue(i + 1);
      width = fm.horizontalAdvance(nameStr);
      rt.setRight(tmpR.left() + 8 + width);
    }
    tmpR.setRight(rt.right());
    m_rects[i + 1] = tmpR;
    rt.moveLeft(rt.right() + 4);
  }
}

bool BondDetailTitle::DrawShowText(const QRect& rcRect, const QString& stText,
                                   QStylePainter* render, QColor pSb, QFont f,
                                   QTextOption to, bool bValue) {
  bool bEllipsis = false;
  if (stText.isEmpty()) return bEllipsis;
  QFontMetrics fm(f);
  int w = fm.horizontalAdvance(stText);

  QString txt = stText;
  if (w > rcRect.width()) {
    bEllipsis = true;
    txt = fm.elidedText(stText, Qt::TextElideMode::ElideRight, rcRect.width());
  }
  render->save();
  render->setPen(pSb);
  if (bValue) {
    QFont f = font();
    f.setBold(true);
    render->setFont(f);
  }
  render->drawText(rcRect, txt, to);
  render->restore();
  return bEllipsis;
}

void BondDetailTitle::jumpCrmBond() {
  if (m_data->crmType() == crm_crm || m_data->crmType() == crm_cln) {
    const BOND_CRM_CLAUSE* crmPtr =
        QBCRMBond::instance().GetBondByKey(m_data->bond().GetBondKey());
    if (crmPtr)
      QbBondModule::instance().app()->execCommand(CMD_BondDetail,
                                                  crmPtr->ReferBondKey.data());
  } else {
    const BOND_CRM_CLAUSE* crmPtr = QBCRMBond::instance().GetBondByReferKey(
        m_data->bond().GetCombBondKey());
    if (crmPtr) {
      CBondContainer& cont = CBondContainer::instance();
      int bondIndex = -1;
      for (int nL = 0; nL < 3; nL++) {
        switch (nL) {
          case 0:
            bondIndex =
                cont.GetBondIndex(crmPtr->BondKey, CBondContainer::lmCIB);
            break;
          case 1:
            bondIndex =
                cont.GetBondIndex(crmPtr->BondKey, CBondContainer::lmSSE);
            break;
          case 2:
            bondIndex =
                cont.GetBondIndex(crmPtr->BondKey, CBondContainer::lmSZE);
            break;
          default:
            break;
        }

        if (cont.IsValidIndex(bondIndex)) {
          const CBondInfo& bi = cont.ElementAtR(bondIndex);
          QbBondModule::instance().app()->execCommand(CMD_BondDetail,
                                                      bi.GetCombBondKey());
          break;
        }
      }
    }
  }
}
